package cn.yr.clock.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.yr.clock.domain.entity.*;
import cn.yr.clock.handler.CacheUserHandler;
import cn.yr.clock.handler.EmailHandler;
import cn.yr.clock.handler.EngineHandler;
import cn.yr.clock.mapper.RecordMapper;
import cn.yr.clock.service.EnginePrizeRelService;
import cn.yr.clock.service.PrizeInstanceService;
import cn.yr.clock.service.RecordService;
import cn.yr.common.exception.ret.Ret;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;

@Service("recordService")
public class RecordServiceImpl extends ServiceImpl<RecordMapper, Record> implements RecordService {

    @Autowired
    private RecordMapper recordMapper;

    @Autowired
    private EngineHandler engineHandler;
    @Autowired
    private EnginePrizeRelService enginePrizeRelService;
    @Autowired
    private EmailHandler emailHandler;
    @Value("${cycleDayNum:42}")
    private Integer cycleDayNum;
    @Autowired
    private PrizeInstanceService prizeInstanceService;

    @Override
    public void addRecord(Record record) {
        recordMapper.insert(record);
    }

    @Override
    @Transactional
    public Ret clock(Record record, Long userId, Date clockTime) {
        /**
         * 今天是否已打卡
         */
        Boolean aBoolean = this.hasRecordToday(userId, clockTime);
        if (aBoolean) {
            return Ret.error("今天已经打卡了哦");
        }
        Record lastRecord = this.getLastRecord(userId);
        if (ObjectUtil.isNotNull(lastRecord) && DateUtil.betweenDay(clockTime, lastRecord.getClockTime(), true) == 1) {
            record.setContinuousNum(lastRecord.getContinuousNum() + 1);
        } else {
            record.setContinuousNum(1);
        }

        //打卡 插入打卡记录
        record.setClockTime(clockTime);
        record.setClockUser(userId);
        this.addRecord(record);
        engineHandler.clearCache();
        //达到的奖励
        ArrayList<EnginePrizeRel> list = new ArrayList<>(3);
        Engine sumClock = engineHandler.isSumClock(userId);
        if (ObjectUtil.isNotNull(sumClock)) {
            EnginePrizeRel enginePrizeRel = new EnginePrizeRel();
            enginePrizeRel.setEngineId(sumClock.getEngineId());
            enginePrizeRel.setPrizeId(sumClock.getPrizeId());
            enginePrizeRel.setStatus(0);
            enginePrizeRel.setUserId(userId);
            enginePrizeRel.setCreateTime(new Date());
            list.add(enginePrizeRel);
        }
        Engine continuousClock = engineHandler.isContinuousClock(userId);
        if (ObjectUtil.isNotNull(continuousClock)) {
            EnginePrizeRel enginePrizeRel2 = new EnginePrizeRel();
            enginePrizeRel2.setEngineId(continuousClock.getEngineId());
            enginePrizeRel2.setPrizeId(continuousClock.getPrizeId());
            enginePrizeRel2.setStatus(0);
            enginePrizeRel2.setUserId(userId);
            enginePrizeRel2.setCreateTime(new Date());
            list.add(enginePrizeRel2);
        }
        Engine cycleNum = engineHandler.isCycleNum(userId);
        if (ObjectUtil.isNotNull(cycleNum)) {
            EnginePrizeRel enginePrizeRel3 = new EnginePrizeRel();
            enginePrizeRel3.setEngineId(cycleNum.getEngineId());
            enginePrizeRel3.setPrizeId(cycleNum.getPrizeId());
            enginePrizeRel3.setStatus(0);
            enginePrizeRel3.setUserId(userId);
            enginePrizeRel3.setCreateTime(new Date());
            Integer cycle = ((engineHandler.sumClock(userId) + 1) / cycleDayNum) + 1;
            enginePrizeRel3.setRounds(cycle);
            list.add(enginePrizeRel3);
        }
        if (list.size() > 0) {
            enginePrizeRelService.saveBatch(list);
        }
        ThreadUtil.execute(() -> emailHandler.recordSendEmail(record));
        return Ret.success();
    }

    @Transactional
    @Override
    public Ret supplementClock(Record record, Long userId, Date clockTime) {
        QueryWrapper<PrizeInstance> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("prize_id", 1);
        wrapper.isNull("verification_time");
        PrizeInstance prizeInstance = prizeInstanceService.getOne(wrapper);
        if (ObjectUtil.isNull(prizeInstance)) {
            return Ret.error("您暂无偷懒卡，无法补卡");
        }
        /* 核销掉偷懒卡 */
        prizeInstanceService.verifyPrize(prizeInstance.getPrizeCode());
        return clock(record, userId, clockTime);
    }

    @Override
    public Record getLastRecord(Long userId) {
        return recordMapper.selectLastRecord(userId);
    }

    @Override
    public Integer selectContinuous(Long userId) {
        return recordMapper.selectContinuous(userId);
    }

    @Override
    public Integer sumRecordByUserId(Long userId) {
        final QueryWrapper<Record> wrapper = new QueryWrapper<>();
        wrapper.eq("clock_user", userId);
        return recordMapper.selectCount(wrapper);
    }

    /**
     * 今天是否已经打卡
     *
     * @param userId
     * @return
     */
    @Override
    public Boolean hasRecordToday(Long userId, Date date) {
        QueryWrapper<Record> wrapper = new QueryWrapper<>();
        DateTime start = DateUtil.beginOfDay(date);
        DateTime end = DateUtil.endOfDay(date);
        wrapper.gt("clock_time", start);
        wrapper.lt("clock_time", end);
        wrapper.eq("clock_user", userId);
        Integer count = recordMapper.selectCount(wrapper);
        return count > 0;
    }
}